using System;
using System.Collections.Generic;
using TTXNA.src.Engine.Stations;
using TTXNA.src.Util;
using Microsoft.Xna.Framework;

namespace TTXNA.src.Engine.Industries
{
    public enum IndustryType { Coal_Mine, Power_Station, Sawmill, Forest, Iron_Ore_Mine, Oil_Refinery, Oil_Rig, Factory, Steel_Mill, Farm, Oil_Wells, Bank }

    public class Industry : Building
    {
        private static Dictionary<IndustryType, IndustryInfo> info;

        private IndustryType industryType;
        private Dictionary<CargoType, int> productionPerMonth;
        private Dictionary<CargoType, float> cargoInStorage;
        private List<Station> stationsInRange;

        static Industry()
        {
            //IndustryLoader loader = new IndustryLoader();
            //info = loader.GetIndustryInfo();
        }

        public Industry(Coordinate coord, RotateType rotType, IndustryType type)
            : base(new Vector3(coord.X, TTXNAGame.World.Map.GetTileMaxHeight(coord.X, coord.Z) / TTXNAGame.HeightScale, coord.Z)) 
        {
            industryType = type;
            productionPerMonth = new Dictionary<CargoType, int>();
            cargoInStorage = new Dictionary<CargoType, float>();
            stationsInRange = new List<Station>();

            Random r = new Random();
            int meshNum = r.Next(Industry.info[type].MeshesAvailable);

            buildingInfo = info[type].GetBuildingInfo(meshNum);

            SetupProduction();
            SetupMesh(coord, rotType, ObjectType.Industry);
            NotifyTiles();
            
        }

        private void SetupProduction()
        {
            foreach (CargoType cType in info[industryType].Produces)
            {
                cargoInStorage[cType] = 0;
                SetProductionAmount(cType, 30);
            }
            foreach (CargoType cType in info[industryType].Accepts)
            {
                cargoInStorage[cType] = 0;
            }
        }

        public void SetProductionAmount(CargoType type, int amount)
        {
            productionPerMonth[type] = amount;
        }

        public int GetProductionAmount(CargoType type)
        {
            return productionPerMonth[type];
        }

        public bool AddStationForDelivery(Station station)
        {
            if (!stationsInRange.Contains(station))
            {
                stationsInRange.Add(station);
                return true;
            }

            return false;
        }

        public decimal ReceiveCargo(CargoPacket packet)
        {
            cargoInStorage[packet.CargoType] += packet.CargoAmount;
            return (decimal)packet.CargoAmount * 200;
        }

        public void Update(TimeSpan timePassed)
        {
            float fractionOfMonth = (float)timePassed.TotalDays / (DateTime.DaysInMonth(TTXNAGame.World.CurrentDate.Year, TTXNAGame.World.CurrentDate.Month));

            foreach (CargoType type in productionPerMonth.Keys)
            {
                cargoInStorage[type] += (float)productionPerMonth[type] * fractionOfMonth;

                foreach (Station station in stationsInRange)
                {
                    station.ReceiveCargoFromIndustry(this, new CargoInfo(type, (cargoInStorage[type] / (float)stationsInRange.Count)));
                    cargoInStorage[type] -= (cargoInStorage[type] / (float)stationsInRange.Count);
                }

                cargoInStorage[type] = 0;
            }
        }

        public IndustryType IndustryType
        {
            get { return industryType; }
        }

        public IndustryInfo Info
        {
            get { return info[IndustryType]; }
        }

    }

    public struct IndustryInfo
    {
        private string industryName;
        private List<CargoType> accepts;
        private List<CargoType> produces;
        private List<BuildingInfo> meshTypes;

        public IndustryInfo(string name)
        {
            industryName = name;
            accepts = new List<CargoType>();
            produces = new List<CargoType>();
            meshTypes = new List<BuildingInfo>();
        }

        public void AddAcceptingCargo(CargoType type)
        {
            accepts.Add(type);
        }

        public void AddProducingCargo(CargoType type)
        {
            produces.Add(type);
        }

        public void AddBuildingInfo(BuildingInfo info)
        {
            meshTypes.Add(info);
        }

        public BuildingInfo GetBuildingInfo(int num)
        {
            return meshTypes[num];
        }

        public List<CargoType> Accepts
        {
            get { return accepts; }
        }

        public List<CargoType> Produces
        {
            get { return produces; }
        }

        public int MeshesAvailable
        {
            get
            {
                return meshTypes.Count;
            }
        }

        public string Name
        {
            get
            {
                return industryName;
            }
        }

    }
}
